/**
 * ES6 引入了一种新的原始数据类型 Symbol ，表示独一无二的值，最大的用法是用来定义对象的唯一属性名。
 * * Symbol 函数栈不能用 new 命令，因为 Symbol 是原始数据类型，不是对象。
 * * 可以接受一个字符串作为参数，为新创建的 Symbol 提供描述，用来显示在控制台或者作为字符串的时候使用，便于区分。
 * * 可访问,但不会出现在 for...in 、 for...of 的循环中
 * * 可以通过 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到。
 */

let a = Symbol('kk')
console.log(a);    //Symbol(kk)
console.log(typeof a);  //symbol

let b = Symbol('kk')
console.log(b, typeof b);
console.log(a === b);    //false


/**
 * Symbol作为对象的属性名,可以保证属性不重名
 * 以下几种有关对象内的写法
 */

//1
let c = Symbol('key1')
let syObject = {}
syObject[c] = 'c'
console.log(syObject);  //{ [Symbol(key1)]: 'c' }

//2
let syObject1 = {
  [c]:'kk'
}
console.log(syObject1);   //{ [Symbol(key1)]: 'kk' }


// 
let object = {
  name: 'mike',
  age: '19',
}

object[c] = 'symKey'
console.log(object);  //{ name: 'mike', age: '19', [Symbol(key1)]: 'symKey' }

console.log(Object.keys(object)); //[ 'name', 'age' ]
console.log(Object.values(object)); //[ 'mike', '19' ]
console.log(Object.entries(object)); //[ [ 'name', 'mike' ], [ 'age', '19' ] ]

console.log(Object.getOwnPropertySymbols(object));  //[ Symbol(key1) ]
console.log(Reflect.ownKeys(object));    //[ 'name', 'age', Symbol(key1) ]


/**
 * Symbol.for() 类似单例模式，
 * 首先会在全局搜索被登记的 Symbol 
 * 中是否有该字符串参数作为名称的 Symbol 值，
 * 如果有即返回该 Symbol 值，
 * 若没有则新建并返回一个以该字符串参数为名称的 Symbol 值，并登记在全局环境中供搜索。
 */
let yellow = Symbol("Yellow");
let yellow1 = Symbol.for("Yellow");
console.log(yellow === yellow1);  //false

let yellow2 = Symbol.for("Yellow");
console.log(yellow1 === yellow2 );    // true


/**
 * Symbol.keyFor() 返回一个已登记的 Symbol 类型值的 key ，
 * 用来检测该字符串参数作为名称的 Symbol 值是否已被登记。
 */
let yellow1 = Symbol.for("Yellow");
console.log(Symbol.keyFor(yellow1));    // Yellow
